package com.agile.leetcode.hutool.cacheutils;

import cn.hutool.cache.Cache;
import cn.hutool.cache.CacheUtil;
import cn.hutool.cache.impl.FIFOCache;
import cn.hutool.cache.impl.LFUCache;
import cn.hutool.cache.impl.TimedCache;
import cn.hutool.core.date.DateUnit;
import org.junit.Test;

import java.util.Iterator;
import java.util.concurrent.TimeUnit;

/**
 * @Author ChenZhangKun
 * @Date 2020/12/30 15:42
 */
public class CacheUtilsDemo {
    /**
     * fifo缓存
     */
    @Test
    public void Fifo() {
        // 创建缓存对象
        FIFOCache<Object, Object> fifoCache = CacheUtil.newFIFOCache(3);
        fifoCache.put("1", "2");
        fifoCache.put("2", "3");
        fifoCache.put("3", "4");
        fifoCache.put("4", "5");
        Iterator<Object> iterator = fifoCache.iterator();
        while (iterator.hasNext()) {
            System.out.println(iterator.next());
        }
    }

    /**
     * 最近最少使用缓存
     */
    @Test
    public void lFUCache() {
        LFUCache<Object, Object> lfuCache = CacheUtil.newLFUCache(3);
        lfuCache.put("key1", "value1", DateUnit.SECOND.getMillis() * 3);
        lfuCache.get("key1");//使用次数+1
        lfuCache.put("key2", "value2", DateUnit.SECOND.getMillis() * 3);
        lfuCache.put("key3", "value3", DateUnit.SECOND.getMillis() * 3);
        // 此时会移除最少使用的元素key2和key3
        lfuCache.put("key4", "value4", DateUnit.SECOND.getMillis() * 3);
        // null
        System.out.println(lfuCache.get("key2"));
    }

    /**
     * 最近最久未使用
     */
    @Test
    public void LRUCache() {
        Cache<String, String> lruCache = CacheUtil.newLRUCache(3);
        // 通过实例化对象创建
        lruCache.put("key1", "value1", DateUnit.SECOND.getMillis() * 3);
        lruCache.put("key2", "value2", DateUnit.SECOND.getMillis() * 3);
        lruCache.put("key3", "value3", DateUnit.SECOND.getMillis() * 3);
        // 使用时间推近
        lruCache.get("key1");
        lruCache.put("key4", "value4", DateUnit.SECOND.getMillis() * 3);
        // 由于缓存容量只有3，当加入第四个元素的时候，根据LRU规则，最少使用的将被移除（2被移除）
        System.out.println(lruCache.get("key"));
    }
    /**
     * 1 底层是hashMap,有并发丢数据风险
     * 2 需要引入hutool config包
     * 3 清理内存是单线程线程池，有空转风险浪费资源
     * 4 不限容量，有内存溢出风险
     *
     *
     * 超时缓存
     */
    @Test
    public void timeCache() throws InterruptedException {
        TimedCache<Object, Object> timedCache = CacheUtil.newTimedCache(100*1000);
        // 1毫秒过期
        timedCache.put("key1", "value1", 1);
        // 5秒过期
        timedCache.put("key2", "value2", DateUnit.SECOND.getMillis() * 3);
        // 没有设置时间->默认过期(4毫秒)
        timedCache.put("key3", "value3");
        // 休眠5s
        TimeUnit.SECONDS.sleep(5);
        // 开启清理
        timedCache.schedulePrune(5);
        timedCache.schedulePrune(5);
        // 拿到第一个值
        System.out.println(timedCache.get("key1"));
        System.out.println(timedCache.get("key2"));
        System.out.println(timedCache.get("key3"));
        System.out.println(timedCache.isEmpty());
        timedCache.cancelPruneSchedule();
    }
}
